home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
D.I.S.C. 4
/
D.I.S.C. 4.adf
/
sources
/
boot_mfm_load.s
< prev
next >
Wrap
Text File
|
1988-01-19
|
12KB
|
416 lines
;
; -> DiskBOOTloader <-
;
; 1990 by Duke/Level Four
;
;Notes:
;a) If you want to load and execute CRUNCHED proggys with this
; loader, you should know the address where the decruncher puts
; your program into memory to be sure that it won't scratch the
; loader-routine. Moreover you have to know that your prog
; will crash if you load it into its own decrunch area!
; To prevent such crashes, you're able to set the address
; of the bootloader and the address where your prog should
; be located after loading by changing the address at
; "Bootstart". !!!DON'T DECREASE THE OFFSET AT "Buffer"!!!
;b) How to install the bootloader on your disk (df0:):
; 1. assemble this loader (with MASTERSEKA)
; 2. bstart_boot <Return> ;calculate boot-checksum
; 3. ws0 <Return> ;(w)rite(s)ector on df(0)
; 4. BEG>start_boot<Return>
; 5. SECTOR>0 <Return> ;start sector 0
; 6. AMOUNT>2 <Return> ;write 2 sectors (1024 bytes)
; Now you must save the program which you want to load to the
; same disk on the correct tracks. You can do that with
; MASTERSEKA, too, by typing:
; 1.ri <Return> ;(r)ead (i)mage
; 2.FILENAME>progname<Return> ;enter name of your program here
; 3.BEG>$40000 <Return> ;load prog. to $40000 for example
; 4.END> <Return> ;load WHOLE prog. just return here
; 5.wt0 <Return> ;(w)rite (t)rack on df(0)
; 6.BEG>$40000 <Return>
; 7.CYLINDER>enter startcylinder here (1 cylinder=2 tracks)
; 8.AMOUNT>enter length of your prog in cylinders (1cyl=11264bytes)
;If you have no MASTERSEKA you can use the Amiga Mon or the C-mon
;to install your program and the loader on disk.
;Ok. Now your AMIGA should load and execute your program correctly.
;signed duke/l4
;MACRO-definitions
color: macro
move.w #\1,$180(a6)
endm
;now we waste diskspace by using the following step-macro (but who
;cares ? - This bootblock is about 920 bytes long...)
step: macro
move.b floppystatus(pc),d0
move.b d0,d1
bclr #0,d0 ;clear DSKSTEP after setting it...STEP!
move.b d0,(a0) ;a0=$bfd100 (CIA-B PRB)
nop ;wait a little
nop
move.b d1,(a0) ;set DSKSTEP back to 1
bsr.l timer ;wait a while
endm
;Statements
Bootstart = $20000
;bootstart=address of bootloader - may be changed!
;
Buffer = Bootstart+$4000
;buffer=address of your decoded program - !!!DON'T DECREASE IT!!!
;
Amount = 22
;amount of tracks to read - may be changed, of course!
first_track = 26
;first track to read - may be changed, too!
;
org $40000 ;$40000 should work without 1MB, too.
load $40000
start_boot:
dc.b "DOS",0 ;DOS id
dc.l 0 ;space for checksum
dc.l $370 ;pointer to rootblock
;
movem.l d0-d7/a0-a6,-(a7)
lea bootstart,a0 ;copy bootblock to bootstart (s. above)
lea start_boot(pc),a1
move.w #$ff,d7 ;copy 1024 bytes
copy_boot:
move.l (a1)+,(a0)+
dbf d7,copy_boot
jmp bootstart+[start-start_boot] ;jump in loader
;
;Here the loading-routine...
S:
Start:
lea $dff000,a6 ;coustom base
lea s(pc),a5 ;addressoffset (bootblock MUST be pc-
;relative)
move.w $01c(a6),oldint-s(a5)
ori.w #$8000,oldint-s(a5)
move.w $002(a6),olddma-s(a5)
ori.w #$8000,olddma-s(a5)
move.w $010(a6),oldadk-s(a5)
ori.w #$8000,oldadk-s(a5)
move.w #$7fff,d0
move.w d0,$096(a6) ;switch dma's off
move.w d0,$09a(a6) ;forbid interrupts
move.w d0,$09c(a6) ;clear intreq
move.w d0,$09e(a6) ;clear adkcon
color 0 ;background color while loading
move.w #$8210,$96(a6) ;diskdma on!
;select DRIVE: 3210
moveq #%0001,d0 ;set right bit for drive 0,1,2 or 3
bsr.l select_drive ;select drive from which you want to read
bsr.l motor_on ;drivemotor on
moveq #0,d0 ;move track number ->d0
bsr.l head_pos ;move head to track 0 (orientation)
bsr.l init_read ;init diskregisters
;
move.w #Amount,trackct-s(a5);set trackcounter
;
Load_tracks:
bchg #1,$bfe001 ;switch led on/off each cylinder
move.w track(pc),d0 ;move head to starttrack
bsr.l head_pos
bsr.l test_disk ;check if disk in drive
;
bsr.l read_track ;read track
bsr.l decode_track ;decode track
;
addq.w #1,track-s(a5) ;next track (add/sub=increase/decrease)
subq.w #1,trackct-s(a5);decrease trackcounter
bne.s load_tracks
;
bsr.l Motor_off ;drivemotor off
move.l bufferpt2(pc),a0;change jump in-address at bufferpt2
jsr (a0) ;jump in loaded program
Exit:
move.w Olddma(pc),$096(a6)
move.w Oldint(pc),$09a(a6)
move.w Oldadk(pc),$09e(a6)
movem.l (a7)+,d0-d7/a0-a6
;Here the normal bootroutine is following. But please notice that it's
;now impossible for the operating-system to access its disk operations
;correctly, because we used the hardware in that direct way without
;permission of the operating-system. That's the reason why you'll see
;a 'not a DOS disk'-requester after returning from the loader. So you
;see that it would be better to jump into the reset-routine instead
;of accessing the following 'find resident'-routine.
;Reset your AMIGA...
; move.l $4.w,a6
; clr.l 38(a6) ;destroy chkbase to force...
; move.l #$fc00d2,$80.w
; trap #0 ;...cold reset
;...or be stupid and try the normal boot-procedure.
move.l $4.w,a6
lea Dosname(pc),a1
jsr -96(a6) ;FindResident()
move.l d0,a0
move.l 22(a0),a0
moveq #0,d0
Rts
dosname:dc.b "dos.library",0
olddma: dc.w 0
oldint: dc.w 0
oldadk: dc.w 0
track: dc.w first_track
trackct:dc.w 0 ;trackcounter
Init_Read:
clr.w $24(a6) ;DSKLEN->forbid diskdma and writing
move.w #$4489,$7e(a6) ;set standard SYNC
move.w #$7f00,$9e(a6) ;clear ADKCON
move.w #$9500,$9e(a6) ;set required bits
move.w #$0002,$9c(a6) ;clear DSKBLK bit
Rts
Read_Track:
clr.w $24(a6) ;DSKLEN->forbid diskdma
lea trackbuff(pc),a0
move.l a0,$20(a6) ;set DSKPTH and DSKPTL
move.w #$9a00,$24(a6) ;enable diskdma and set amount of
move.w #$9a00,$24(a6) ;words+2 to transfer.
Wait_Dma:
btst #1,$1f(a6) ;DSKBLK=0 ?
beq.s Wait_Dma ;yeah=> wait
clr.w $24(a6) ;forbid writing
move.w #$0002,$9c(a6) ;clear DSKBLK
Rts
;Timer A-delay
timer: ;waits ca. 1/100 sec.
move.b #$00,$bfde00 ;clear CRA
move.b #$7f,$bfdd00 ;clear ICR
move.b #$00,$bfd400 ;timer a -low
move.b #$20,$bfd500 ;timer a -high (wait-value=$2000)
move.b #$09,$bfde00 ;set oneshot/start
wait_timer:
btst #0,$bfdd00 ;test ta-bit/that clears ICR
beq.s wait_timer
rts
Wait_ready:
btst #5,$bfe001 ;wait for DRIVEREADY
bne.s Wait_ready ;it's useless here, because the wait-
Rts ;loop is long enough, but......
test_disk:
btst #2,$bfe001
beq.s error
Rts
error: move.w $dff006,$dff180
bra.s error
Select_Drive:
lea floppystatus(pc),a0
lea motorstatus(pc),a1
moveq #-1,d1 ;$ffffffff -> d1
lsl.w #3,d0 ;shift selectbit to right position
eor.b d0,d1 ;selectbit must be zero
move.b d1,(a0) ;save byte ->floppystatus.b
eori.b #$80,d1 ;clear DSKMOTOR-bit
move.b d1,(a1) ;save byte ->motorstatus.b
Rts
Motor_On:
move.b #$7f,$bfd100 ;Bits 0-6 HIGH/Bit 7 LOW
nop
nop
move.b motorstatus(pc),d0
move.b d0,$bfd100 ;DSKMOTOR and DSKSELx LOW
bsr.l Wait_Ready
Rts
Motor_Off:
move.b #$ff,$bfd100 ;Bits 0-7 HIGH
nop
nop
move.b motorstatus(pc),d0
ori.b #$80,d0 ;DSKMOTOR HIGH DSKSELx LOW
move.b d0,$bfd100
Rts
;This routine moves the r/w-head to a track with the number stored
;in d0. A similar routine is also used by the operating-system
;(at $fea3da)
Head_Pos:
lea $bfd100,a0
lea s(pc),a5
tst.w d0 ;track number=0?
beq.l Move_zero ;yeah=>step to track 0
move.w Tracknum(pc),d2 ;current track number
cmp.w d2,d0 ;oldtrack=newtrack ?
beq.s Head_end ;yes=>don't move head
move.w d0,d3
move.b Floppystatus(pc),d1
bset #2,d1 ;select head 0 (lower side)
btst #0,d3 ;track number even ?
beq.s Down_Right ;yes=>head 0 is the right one
bclr #2,d1 ;no, select head 1 (upper side)
Down_Right:
move.b d1,Floppystatus-s(a5)
move.b d1,(a0)
move.w d3,Tracknum-s(a5) ;save new track-number
lsr.w #1,d2 ;d2=current cylinder
lsr.w #1,d3 ;d3=new cylinder
sub.w d3,d2 ;make difference
bmi.s Seek_in ;diff. negativ=> step in
beq.s Head_end
bra.s Seek_out ;diff. positiv=> step out
Seek_in:
bclr #1,d1 ;step in
move.b d1,Floppystatus-s(a5)
neg.w d2 ;make number positive
bra.s Step_Ok
Seek_out:
bset #1,d1 ;step out
move.b d1,Floppystatus-s(a5)
bra.s Step_Ok
HeadStep:
Step ;call step-macro
Step_Ok:
dbf d2,HeadStep
Head_end:
Rts
Move_zero: ;move head to track zero
move.b Floppystatus(pc),d1
bset #2,d1
bset #1,d1
move.b d1,Floppystatus-s(a5)
clr.w Tracknum-s(a5)
Headzero:
btst #4,$bfe001 ;test if zero
beq.s zero1
Step
bra.s Headzero
zero1:
bclr #1,Floppystatus-s(a5)
Step
bset #1,Floppystatus-s(a5)
Step
bra.s Head_end
;
;This routine decodes the block-header and checks the format-sign.
;After this it calculates the checksum from the data-block and
;compares it with the checksum wich is stored in the block-header.
;While calculating the checksum it decodes the data block, of course.
decode_track:
move.l bufferpt(pc),a0 ;pointer to decodebuffer
lea trackbuff(pc),a1 ;pointer to MFMbuffer
moveq #11-1,d5 ;decode 11 blocks (-1 coz dbf)
move.l #$55555555,d3 ;filter for tactbits
decode_all_blocks:
cmpi.w #$4489,(a1)+ ;1st sync-word found ?
bne.s decode_all_blocks ;no=> go on searching
sync_found:
cmpi.w #$4489,(a1) ;2. sync-word found ?
bne.s syncs_ok ;no=> all syncs skipped
addq.w #2,a1 ;yes=>
bra.s sync_found ;search for remaining syncs
syncs_ok: ;decode infoblock
move.l (a1)+,d0 ;odd bits
move.l (a1)+,d1 ;even bits
and.l d3,d0
and.l d3,d1
add.l d0,d0
or.l d1,d0
swap d0
andi.w #$ff00,d0 ;mask format-sign (must be $ff)
cmpi.w #$ff00,d0 ;right value?
bne.s formatrerror ;no==>ERROR!
swap d0
andi.w #$ff00,d0 ;mask sector number*256
add.w d0,d0 ;d0=d0*2 (=sector number*512)
move.l a0,a2 ;address of decodebuffer ->a2
adda.w d0,a2 ;calc. correct destination
adda.w #40,a1 ;address of checksum ->a1
move.l (a1)+,d4 ;decode checksum
move.l (a1)+,d1
and.l d3,d4
and.l d3,d1
add.l d4,d4
or.l d1,d4 ;store checksum ->d4
moveq #128-1,d6 ;decode 128*2 longs to 512 bytes
moveq #0,d2 ;clear datachecksum
decodeblock: ;decode datablock
move.l 512(a1),d1 ;even bits
move.l (a1)+,d0 ;odd bits
eor.l d0,d2 ;calc checksum
eor.l d1,d2 ;dito
and.l d3,d0 ;decode longword
and.l d3,d1
add.l d0,d0
or.l d1,d0
move.l d0,(a2)+ ;store longword in buffer
dbf d6,decodeblock ;decode next longword
and.l d3,d2 ;remove tactbits
cmp.l d4,d2 ;checksum correct ?
bne.s chksumerror ;no=>ERROR!
adda.w #512,a1 ;reach next block
dbf d5,decode_all_blocks
adda.w #$1600,a0 ;bufferadr.+ 1track (5632bytes)
move.l a0,bufferpt-s(a5) ;store new address
Rts
chksumerror:
color $f00 ;backgroundcolor red
st chkflag-s(a5) ;set errorflag to -1
Rts
formatrerror:
color $f00 ;backgroundcolor red
st hdrflag-s(a5) ;set errorflag to -1
Rts
tracknum: dc.w 0
floppystatus: dc.b 0
motorstatus: dc.b 0
chkflag: dc.b 0
hdrflag: dc.b 0
bufferpt: dc.l buffer
bufferpt2: dc.l buffer ;here you can change the jump-
;in address of your prog.
dc.b " Loader by Duke of LEVEL FOUR - ASD "
Even
trackbuff:
endprg:
blk.b 200,0 ;just to clear remaining bytes in mem